<?php

namespace App\Http\Controllers\Api\V1_0_0;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;
use SebastianBergmann\CodeCoverage\Report\PHP;

class RedisController extends Controller
{
    //redis用于排行榜
    public function rank()
    {
        //$redis = new Redis();
        $redis = Redis::connection();
        //假设一个消费金额排行榜 consume_amount
        $redisKey = 'consume_amount';
        $uid = 330621;
        $redis->zadd($redisKey, 101.05, 330621);
        $redis->zadd($redisKey, 1101, 336567);
        $redis->zadd($redisKey, 80.5, 347865);
        //写入已有member会自动更新其值
        $redis->zadd($redisKey, 1680, 336567);
        //另外还有一种方式是直接在已有member上进行增减操作
        $redis->zincrby($redisKey, 8888, $uid);
        //获取总人数
        echo $redis->zcard($redisKey).PHP_EOL;
        //正向 也就是 消费金额升序 获取数据先看下是长什么样
        $list = $redis->zrange($redisKey, 0, -1, true);
        var_dump($list);
        //获取前2名
        $top = $redis->zrevrange($redisKey, 0, 1);
        var_dump($top);
        //获取指定 消费金额 之间的数量
        echo $redis->zcount($redisKey, 1000, 5000).PHP_EOL;
        //获取指定 消费金额 之间的数据
        $list = $redis->zrangebyscore($redisKey, 1000, 5000);
        var_dump($list);
        //获取指定数据并带上消费金额信息
        $list = $redis->zrangebyscore($redisKey, 1000, 5000, ['withscores' => true]);
        var_dump($list);
        echo PHP_EOL;
        //获取本人名次
        echo $redis->zrevrank($redisKey, $uid).PHP_EOL;
        //获取本人消费金额
        echo $redis->zscore($redisKey, $uid).PHP_EOL;
        exit;
    }

    //redis用于计数器
    public function count()
    {
        //1. 文章的浏览数量
        $redisKey = 'view_num';
        $redis = Redis::connection();
        //每进入文章详情页一次，计数增加一次
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        echo $redis->get($redisKey).PHP_EOL;
        //暗箱操作，增加或减少指定数值
        $redis->incrby($redisKey, 5);
        echo $redis->get($redisKey).PHP_EOL;
        $redis->decrby($redisKey, 3);
        echo $redis->get($redisKey).PHP_EOL;
        //2. 限购数量
        $redisKey = 'buy_list';
        $uid = 336699;
        $redis->sadd($redisKey, 336699);
        $redis->sadd($redisKey, 354566);
        $redis->sadd($redisKey, 352366);
        $redis->sadd($redisKey, 351166);
        //已存在的添加失败，sadd 返回本次新添加的数量
        $ret = $redis->sadd($redisKey, $uid);
        if (!$ret) {
            echo '每人限购一件!'.PHP_EOL;
        }
        //获取集合中的数据数量
        echo $redis->scard($redisKey).PHP_EOL;
        //获取集合中的所有元素
        $list = $redis->smembers($redisKey);
        var_dump($list);
        //判断指定数据是否存在于集合中
        $isBuy = $redis->sismember($redisKey, $uid);
        echo $isBuy ? '已购买':'未购买';
        echo PHP_EOL;
        //3. 限流 todo incr存在一个陷阱，默认是无过期时间的
        $redisKey = 'throttles_336699';
        $ret = $redis->incr($redisKey, 1);
        //确定是首次，然后增加过期时间的设置
        if ($ret && $ret === 1) {
            $redis->expire($redisKey, 10);//本该60，但为了程序不sleep太久
        }
        //防止并发操作引起的 过期时间未设置的情况
        if ($redis->ttl($redisKey) === -1) {
            //todo 已经是永不过期的key，好像不支持覆写有效期
            $redis->expire($redisKey, 10);
        }
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        if ($redis->get($redisKey) > 5) {
            echo '一分钟内最多访问5次!111'.PHP_EOL;
        }
        sleep(10);
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        $redis->incr($redisKey, 1);
        if ($redis->get($redisKey) > 5) {
            echo '一分钟内最多访问5次!222'.PHP_EOL;
        }
        echo $redis->get($redisKey).PHP_EOL;
        exit;
    }
}
